# -*- coding: utf-8 -*-
# Created by shu2015626 on 2019-10-15
"""
定义基础的celery task base方便绑定的时候处理行管任务
参考：https://docs.celeryproject.org/en/latest/userguide/tasks.html#basics
"""
import logging
from celery import states
from celery.task import Task

from tasks_info.models import TasksInfo

logger = logging.getLogger("tasks")


class CeleryTaskBase(Task):
    """
    使用示例：@app.task(base=CeleryTaskBase,bind=True)
    这样就可以进行一些特定事件的处理。
    将所有任务的监控信息存储放到这里！
    """
    # def on_success(self, retval, task_id, args, kwargs):  # 任务成功执行
    #     obj, created = TasksInfo.objects.update_or_create(
    #         task_id=task_id,
    #         defaults={
    #             "result": retval,
    #             "status": states.SUCCESS,
    #             "hostname": getattr(self.request, 'hostname', None) if self.request else None,
    #             "task_name": getattr(self.request, 'task', None) if self.request else None,
    #             "operate_file": getattr(self.request, 'operate_file', None) if self.request else None,
    #             "task_args": args,
    #             "task_kwargs": kwargs,
    #         }
    #     )
    #     logger.info(f'task id:{task_id}, {states.SUCCESS}! arg: {args}, kwargs: {kwargs}. ')
    #
    def on_failure(self, exc, task_id, args, kwargs, einfo):  # 任务失败执行
        obj, created = TasksInfo.objects.update_or_create(
            task_id=task_id,
            defaults={
                "status": states.FAILURE,
                "hostname": getattr(self.request, 'hostname', None) if self.request else None,
                "task_name": getattr(self.request, 'task', None) if self.request else None,
                "operate_file": getattr(self.request, 'operate_file', None) if self.request else None,
                "task_args": args,
                "task_kwargs": kwargs,
                "traceback": einfo,
            }
        )
        logger.error(f'task id:{task_id}, {states.FAILURE}! arg: {args}, kwargs: {kwargs}. errors: {einfo}')

    def on_retry(self, exc, task_id, args, kwargs, einfo):  # 任务重试执行
        obj, created = TasksInfo.objects.update_or_create(
            task_id=task_id,
            defaults={
                "status": states.RETRY,
                "hostname": getattr(self.request, 'hostname', None) if self.request else None,
                "task_name": getattr(self.request, 'task', None) if self.request else None,
                "operate_file": getattr(self.request, 'operate_file', None) if self.request else None,
                "task_args": args,
                "task_kwargs": kwargs,
                "traceback": einfo,
            }
        )
        logger.warning(f'task id:{task_id}, {states.RETRY}! arg: {args}, kwargs: {kwargs}. errors: {einfo}')

    def after_return(self, status, retval, task_id, args, kwargs, einfo):
        # 状态为失败、重试的任务已经处理过了，直接返回
        # 不统一放在这里的原因是，on_failure的时候，此函数拿不到异常信息。
        if status in [states.FAILURE, states.RETRY]:
            return

        obj, created = TasksInfo.objects.update_or_create(
            task_id=task_id,
            defaults={
                "result": str(retval),
                "status": status,
                "hostname": getattr(self.request, 'hostname', None) if self.request else None,
                "task_name": getattr(self.request, 'task', None) if self.request else None,
                "operate_file": getattr(self.request, 'operate_file', None) if self.request else None,
                "task_args": args,
                "task_kwargs": kwargs,
                "traceback": einfo,
            }
        )

        # if status == states.FAILURE:
        #     logger.error(f'task id:{task_id}, {status}! arg: {args}, kwargs: {kwargs}. errors: {einfo}')
        # elif status == states.RETRY:
        #     logger.warning(f'task id:{task_id}, {status}! arg: {args}, kwargs: {kwargs}. errors: {einfo}')
        # else:
        #     logger.info(f'task id:{task_id}, {status}! arg: {args}, kwargs: {kwargs}. errors: {einfo}')

        logger.info(f'task id:{task_id}, {status}! arg: {args}, kwargs: {kwargs}. errors: {einfo}')